/* 类型判断式 */

// 如果你想直接通过代码控制类型的改变， 你可以自定义一个类型保护。
// 实现方式是定义一个函数，这个函数返回的类型是类型判断式
// pet is Fish就是我们的类型判断式，
// 一个类型判断式采用 parameterName is Type的形式，但 parameterName 必须是当前函数的参数名。
type Fish9 = AnimalType & { swim: () => void };
type Bird9 = AnimalType & { fly: () => void };

function getSmallPet() {
  const fish: Fish9 = { name: 'fish', swim: () => {} };
  const bird: Bird9 = { name: 'bird',  fly: () => {} };
  return Math.random() < 0.5 ? fish : bird;
}

function isFish(pet: Fish9 | Bird9): pet is Fish9 {
  return (pet as Fish9).swim !== undefined;
}

let pet = getSmallPet();

if (isFish(pet)) {
  pet.swim(); // let pet: Fish
} else {
  pet.fly(); // let pet: Bird
}

const zoo: (Fish9 | Bird9)[] = [getSmallPet(), getSmallPet(), getSmallPet()];
const underWater1: Fish9[] = zoo.filter(isFish);
// or, equivalently
const underWater2: Fish9[] = zoo.filter(isFish) as Fish9[];

// 在更复杂的例子中，判断式可能需要重复写
const underWater3: Fish9[] = zoo.filter((pet): pet is Fish9 => {
  if (pet.name === "sharkey") return false;
  return isFish(pet);
});